﻿using System;
using System.Collections.Generic;
using System.Configuration ;
using System.IO ;
using System.Linq;
using System.Text ;
using BoYuanCore.CoreCodeTemplates ;
using BoYuanCore.CoreCodeTemplates.DBMappingRules ;
using BoYuanCore.CoreCodeTemplates.FineUICore.Template ;
using Template_ModelFirst = BoYuanCore.CoreCodeTemplates.FineUICore.Template ;
using FineUIPro ;
using FreeSql.DatabaseModel;
using DbColumnInfo = BoYuanCore.CoreCodeTemplates.DbColumnInfo;
using FreeSql.Aop;
using FreeSql.Internal;
using MySql.Data.MySqlClient;
using Npgsql;
using Oracle.ManagedDataAccess.Client;
using System.Data.SqlClient;

namespace BoYuanCore.CodeGenerator.code
{
    public partial class CodeBasePage : FineUIPage
    {

        /// <summary>
        /// 需要手动销毁
        /// </summary>
        /// <returns></returns>
        public IFreeSql MyInstance()
        {
            return InitFreeSqlInstance(GetDbType(), GetConnectionString());
        }


        /// <summary>
        /// 获取数据连接，需要手动销毁ifreesql
        /// </summary>
        /// <param name="dbType"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public IFreeSql InitFreeSqlInstance(string dbType, string url)
        {
            IFreeSql DB;
            switch (dbType)
            {
                default: //"SqlServer"
                    DB = new FreeSql.FreeSqlBuilder()
                        //.UseConnectionString(FreeSql.DataType.SqlServer, url)//为了放弃预热，放弃内部对象连接池技术，采用自定义UseConnectionFactory
                        .UseConnectionFactory(FreeSql.DataType.SqlServer, () => new SqlConnection(url))
                        .UseAutoSyncStructure(false) //自动同步实体结构到数据库
                        //.UseMonitorCommand(cmd => Logger.Default.Debug(cmd.CommandText))
                        .UseNoneCommandParameter(true)
                        .Build();
                    break;

                case "MySql":
                    DB = new FreeSql.FreeSqlBuilder()
                        //.UseConnectionString(FreeSql.DataType.MySql, url)//为了放弃预热，放弃内部对象连接池技术，采用自定义UseConnectionFactory
                        .UseConnectionFactory(FreeSql.DataType.MySql, () => new MySqlConnection(url))
                        .UseAutoSyncStructure(false) //自动同步实体结构到数据库
                        //.UseMonitorCommand(cmd => Logger.Default.Debug(cmd.CommandText))
                        .UseNoneCommandParameter(true)
                        .Build();

                    break;

                case "Oracle":
                    DB = new FreeSql.FreeSqlBuilder()
                        //.UseConnectionString(FreeSql.DataType.Oracle, url)//为了放弃预热，放弃内部对象连接池技术，采用自定义UseConnectionFactory
                        .UseConnectionFactory(FreeSql.DataType.Oracle, () => new OracleConnection(url))
                        .UseAutoSyncStructure(false) //自动同步实体结构到数据库
                        //.UseMonitorCommand(cmd => Logger.Default.Debug(cmd.CommandText))
                        .UseNoneCommandParameter(true)
                        .UseNameConvert(NameConvertType.ToUpper)//表名称全局大写
                        .Build(); //请务必定义成 Singleton 单例模式
                    break;

                case "PostgreSQL":
                    DB = new FreeSql.FreeSqlBuilder()
                        //.UseConnectionString(FreeSql.DataType.PostgreSQL, url)//为了放弃预热，放弃内部对象连接池技术，采用自定义UseConnectionFactory
                        .UseConnectionFactory(FreeSql.DataType.PostgreSQL, () => new NpgsqlConnection(url))
                        .UseAutoSyncStructure(false) //自动同步实体结构到数据库
                        //.UseMonitorCommand(cmd => Logger.Default.Debug(cmd.CommandText))
                        .UseNoneCommandParameter(true)
                        .UseNameConvert(NameConvertType.ToLower)//表名称全局小写
                        .Build(); //请务必定义成 Singleton 单例模式
                    break;
            }

            EventHandler<ConfigEntityPropertyEventArgs> tempEventHandler = (s, ce) =>
            {
                //默认情况 c# 枚举会映射为 MySql Enum 类型，如果想映射为 int 在 FreeSqlBuilder Build 之后执行以下 Aop 统一处理。https://github.com/dotnetcore/FreeSql/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
                //if (DB.Ado.DataType == DataType.MySql && ce.Property.PropertyType.IsEnum)

                //为了LookSQL能正常显示Enum特性的值
                if (ce.Property.PropertyType.IsEnum)
                    ce.ModifyResult.MapType = typeof(int);
            };
            DB.Aop.ConfigEntityProperty -= tempEventHandler;//防止重复添加事件
            DB.Aop.ConfigEntityProperty += tempEventHandler;


            return DB;
        }

        public string GetConnectionString()
        {
            return Session["db"] != null ? Session["db"].ToString() : ConfigurationManager.AppSettings["ConnectionString"] ;
        }
        public string GetDbType()
        {
            return Session["dbtype"] != null ? Session["dbtype"].ToString() : "Sqlserver";
        }

        /// <summary>
        ///  获取表信息
        /// </summary>
        /// <param name="likeName"></param>
        /// <returns></returns>
        public List<string> GetTableInfos(string likeName = "")
        {
            List<string> tableList;
            using (var db = MyInstance())
            {
                tableList = db.DbFirst.GetTablesByDatabase()
                    .OrderBy(p => p.Name)
                    .Select(p => p.Name)
                    .ToList();
            }

            if (likeName.Length == 0)
            {
                return tableList;
            }
            else
            {
                return tableList
                    .Where(p => p.IndexOf(likeName, StringComparison.OrdinalIgnoreCase) >= 0)
                    .OrderBy(p => p)
                    .ToList();
            }
        }


        /// <summary>
        /// 获取字段信息集合，根据表
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <returns></returns>
        public List<DbColumnInfo> GetColumnDataByTableName(string tableName)
        {
            DbTableInfo table;
            using (var db = MyInstance())
            {
                table = db.DbFirst.GetTablesByDatabase().FirstOrDefault(p => p.Name == tableName);
            }

            var list = table?.Columns.Select(p => new DbColumnInfo()
            {
                TableName = p.Table.Name,
                DbColumnName = p.Name,
                CsType = p.CsType,
                IsIdentity = p.IsIdentity,
                IsNullable = p.IsNullable,
                MaxLength = p.MaxLength,
                Coment = p.Coment,
                DefaultValue = p.DefaultValue,
                IsPrimaryKey = p.IsPrimary,
                DbTypeText = p.DbTypeText,
                DbTypeTextFull = p.DbTypeTextFull
            }).ToList();

            return list;
        }

        /// <summary>
        /// 获取表信息集，根据表名称
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <returns></returns>
        public DbTableInfo GetTableInfoByTableName(string tableName)
        {
            DbTableInfo mo;
            using (var db = MyInstance())
            {
                mo = db.DbFirst.GetTablesByDatabase(db.DbFirst.GetDatabases()[0]).FirstOrDefault(p => p.Name == tableName);
            }
               
            if (mo != null)
            {
                mo.Comment = mo.Comment ?? String.Empty ;
                return mo ;
            }

            return null;
        }

        /// <summary>
        /// 生成FineUICore代码到指定的位置
        /// </summary>
        /// <param name="savePath">生成代码的物理地址</param>
        /// <param name="table">表信息实体</param>
        public void CreateFineUICoreCode(string savePath, TableModel table,bool haveListPage = true, bool haveAddPage = true, bool haveViewPage = false, bool haveEGPage = false, bool haveOPPage = false)
        {
            string controllersPath = savePath + "/" + table.Namespace2Str + "/Controllers";// c:/code/Areas/Admin/Controllers
            string viewsPath = savePath + "/" + table.Namespace2Str + "/Views/" + table.TableNameToClassName;// c:/code/Areas/Admin/views/SysAdmin

            if (!Directory.Exists(controllersPath))
            {
                Directory.CreateDirectory(controllersPath); //在根目录下建立文件夹
            }

            if (!Directory.Exists(viewsPath))
            {
                Directory.CreateDirectory(viewsPath); //在根目录下建立文件夹
            }

            string templateInfo;

            //controllers
            templateInfo = ControllerTemplate.GetCode(table,  haveListPage , haveAddPage , haveViewPage , haveEGPage , haveOPPage);
            System.IO.File.WriteAllText(controllersPath + "/" + table.TableNameToClassName + "Controller.cs", templateInfo, Encoding.UTF8);

            //views
            templateInfo = AddcshtmlTemplate.GetCode(table);
            System.IO.File.WriteAllText(viewsPath + "/Add.cshtml", templateInfo, Encoding.UTF8);

            templateInfo = ListPagecshtmlTemplate.GetCode(table);
            System.IO.File.WriteAllText(viewsPath + "/ListPage.cshtml", templateInfo, Encoding.UTF8);
        }

        /// <summary>
        /// 获取高亮代码
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public string ShowHighlightCode(string code)
        {
            return "<pre><code>" + TextBoxToHtml(code)+ "</code></pre>";
        }

        ///<summary> 
        ///TextBox文本转成html字符实体 
        ///</summary> 
        ///<param  name="text">TextBox文本</param> 
        ///<returns></returns> 
        public static string TextBoxToHtml(string text)
        {
            StringBuilder sb = new StringBuilder(text);
            sb.Replace("&", "&amp");
            sb.Replace("\"", "&quot;");
            sb.Replace(" ", "&nbsp;");
            sb.Replace("<", "&lt;");
            sb.Replace(">", "&gt;");
            sb.Replace("\n", "<br/>");
            return sb.ToString();
        }
    }
}